package net.xdclass.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.reactivex.Single;
import lombok.extern.slf4j.Slf4j;
import net.xdclass.config.RabbitMQConfig;
import net.xdclass.enums.BizCodeEnum;
import net.xdclass.enums.CouponStateEnum;
import net.xdclass.enums.ProductOrderStateEnum;
import net.xdclass.enums.StockTaskStateEnum;
import net.xdclass.exception.BizException;
import net.xdclass.feign.ProductOrderFeignService;
import net.xdclass.interceptor.LoginInterceptor;
import net.xdclass.model.CouponRecordDO;
import net.xdclass.mapper.CouponRecordMapper;
import net.xdclass.model.CouponRecordMessage;
import net.xdclass.model.CouponTaskDO;
import net.xdclass.model.LoginUser;
import net.xdclass.request.LockCouponRecordRequest;
import net.xdclass.service.CouponRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.xdclass.service.CouponTaskService;
import net.xdclass.until.CommonUtil;
import net.xdclass.until.JsonData;
import net.xdclass.vo.CouponRecordVO;
import org.checkerframework.checker.units.qual.A;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 二当家小D
 * @since 2022-02-08
 */
@Slf4j
@Service
public class CouponRecordServiceImpl extends ServiceImpl<CouponRecordMapper, CouponRecordDO> implements CouponRecordService {

    @Autowired
    private CouponTaskService couponTaskService;
    @Autowired
    private ProductOrderFeignService productOrderFeignService;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RabbitMQConfig rabbitMQConfig;

    @Override
    public Map<String, Object> page(int page, int size) {
        LoginUser loginUser = LoginInterceptor.loginUserThreadLocal.get();
        Page<CouponRecordDO> couponRecordDOPage = new Page<CouponRecordDO>(page, size);
        Page<CouponRecordDO> couponRecordDOPage1 = baseMapper.selectPage(couponRecordDOPage,
                new QueryWrapper<CouponRecordDO>()
                        .eq("user_id", loginUser.getId())
                        .orderByDesc("create_time"));
        Map<String, Object> stringObjectMap = CommonUtil.beanProcess(couponRecordDOPage1, CouponRecordVO.class);
        return stringObjectMap;
    }

    @Override
    public CouponRecordVO findById(long recordId) {
        LoginUser loginUser = LoginInterceptor.loginUserThreadLocal.get();
        CouponRecordDO couponRecordDO = baseMapper.selectOne(new QueryWrapper<CouponRecordDO>()
                .eq("id", recordId)
                .eq("user_id", loginUser.getId()));
        if (couponRecordDO == null) {
            return null;
        }
        CouponRecordVO couponRecordVO = new CouponRecordVO();
        BeanUtils.copyProperties(couponRecordDO, couponRecordVO);
        return couponRecordVO;
    }

    @Override
    public JsonData lockCouponRecords(LockCouponRecordRequest recordRequest) {
        LoginUser loginUser = LoginInterceptor.loginUserThreadLocal.get();
        String orderOutTradeNo = recordRequest.getOrderOutTradeNo();
        List<Long> lockCouponRecordIds = recordRequest.getLockCouponRecordIds();
        int rows = baseMapper.lockUseStateBatch(loginUser.getId(), CouponStateEnum.USED, lockCouponRecordIds);

        List<CouponTaskDO> couponTaskDOList = lockCouponRecordIds.stream().map(obj -> {
            CouponTaskDO couponTaskDO = new CouponTaskDO();
            couponTaskDO.setCreateTime(new Date());
            couponTaskDO.setOutTradeNo(orderOutTradeNo);
            couponTaskDO.setCouponRecordId(obj);
            couponTaskDO.setLockState(StockTaskStateEnum.LOCK.name());
            return couponTaskDO;
        }).collect(Collectors.toList());
        boolean b = couponTaskService.saveBatch(couponTaskDOList, rows);
        log.info("优惠券记录锁定 rows={}", rows);
        log.info("新增优惠券记录task boolean={}", b);

        if (rows > 0 && b) {
            for (CouponTaskDO i : couponTaskDOList) {
                CouponRecordMessage couponRecordMessage = new CouponRecordMessage();
                couponRecordMessage.setOutTradeNo(orderOutTradeNo);
                couponRecordMessage.setTaskId(i.getId());
                rabbitTemplate.convertAndSend(rabbitMQConfig.getEventExchange(), rabbitMQConfig.getCouponReleaseDelayRoutingKey(), couponRecordMessage);
                log.info("优惠券锁定消息发送成功:{}", couponRecordMessage.toString());
            }
            return JsonData.buildSuccess();
        } else {
            throw new BizException(BizCodeEnum.COUPON_RECORD_LOCK_FAIL);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public boolean releaseCouponRecord(CouponRecordMessage recordMessage) {
        CouponTaskDO couponTaskDO = couponTaskService.getBaseMapper().selectOne(new QueryWrapper<CouponTaskDO>()
                .eq("id", recordMessage.getTaskId()));
        if (couponTaskDO == null) {
            log.warn("工作单不存在,消息:{}", recordMessage);
            return true;
        }
        //lock状态处理
        if (couponTaskDO.getLockState().equalsIgnoreCase(StockTaskStateEnum.LOCK.name())) {
            //查询订单状态
            JsonData jsonData = productOrderFeignService.queryProductOrderState(recordMessage.getOutTradeNo());
            if (jsonData.getCode() == 0) {
                //正常响应 判断订单状态
                String state = jsonData.getData().toString();
                if (ProductOrderStateEnum.NEW.name().equalsIgnoreCase(state)) {
                    log.warn("订单状态是NEW,返回给消息队列,重新投递");
                    return false;
                }
                if (ProductOrderStateEnum.PAY.name().equalsIgnoreCase(state)) {
                    couponTaskDO.setLockState(StockTaskStateEnum.FINISH.name());
                    couponTaskService.update(couponTaskDO, new QueryWrapper<CouponTaskDO>()
                            .eq("id", recordMessage.getTaskId()));
                    log.info("订单已经支付,修改库存锁定工作单FINISH状态:{}", recordMessage);
                    return true;
                }
            }
            log.warn("订单不存在,或者被取消,确认消息,修改状态为CANCEL,恢复优惠劵为NEW,message:{}", recordMessage);
            couponTaskDO.setLockState(StockTaskStateEnum.CANCEL.name());
            couponTaskService.update(couponTaskDO, new QueryWrapper<CouponTaskDO>()
                    .eq("id", recordMessage.getTaskId()));
            baseMapper.updateState(couponTaskDO.getCouponRecordId(), CouponStateEnum.NEW.name());

            return true;
        } else {
            log.warn("工作单状态不是LOCK,state={},消息体={}", couponTaskDO.getLockState(), recordMessage);
            return true;
        }
    }
}
